package com.hyt.it.ogt.ykcj.service.exam.impl;

import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.Collator;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.hssf.usermodel.HSSFDataFormatter;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.hyt.it.ogt.ykcj.common.constant.DictType;
import com.hyt.it.ogt.ykcj.common.constant.ImportFieldConstants;
import com.hyt.it.ogt.ykcj.common.core.domain.AjaxResult;
import com.hyt.it.ogt.ykcj.common.enums.BizErrorCode;
import com.hyt.it.ogt.ykcj.common.exception.CustomException;
import com.hyt.it.ogt.ykcj.common.utils.AsciiUtil;
import com.hyt.it.ogt.ykcj.common.utils.DateUtils;
import com.hyt.it.ogt.ykcj.common.utils.DictUtils;
import com.hyt.it.ogt.ykcj.common.utils.IdUtils;
import com.hyt.it.ogt.ykcj.common.utils.SecurityUtils;
import com.hyt.it.ogt.ykcj.common.utils.StringUtils;
import com.hyt.it.ogt.ykcj.common.utils.bean.BeanUtils;
import com.hyt.it.ogt.ykcj.domain.exam.ExamInfo;
import com.hyt.it.ogt.ykcj.domain.exam.ExamPostInfo;
import com.hyt.it.ogt.ykcj.domain.grade.ServantExamineeInfo;
import com.hyt.it.ogt.ykcj.domain.vo.ExamPostInfoReq;
import com.hyt.it.ogt.ykcj.domain.vo.ExamPostInfoRsp;
import com.hyt.it.ogt.ykcj.domain.vo.ExamPostInfoVo;
import com.hyt.it.ogt.ykcj.domain.vo.ExamScoreLineReq;
import com.hyt.it.ogt.ykcj.domain.vo.ImportPostInfoVo;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamPostInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.exam.ExamPostScoreLineSettingSubMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.ServantExamineeInfoMapper;
import com.hyt.it.ogt.ykcj.mapper.grade.ServantExamineeSubjectGradeMapper;
import com.hyt.it.ogt.ykcj.mapper.system.SysDictDataMapper;
import com.hyt.it.ogt.ykcj.mapper.system.SysDistrictMapper;
import com.hyt.it.ogt.ykcj.service.exam.IChangedExamInfoService;
import com.hyt.it.ogt.ykcj.service.exam.IExamPostInfoService;
import com.hyt.it.ogt.ykcj.service.grade.ExportUtils;
import com.hyt.it.ogt.ykcj.service.grade.ImportAbstractService;

/**
 * 招考职位信息Service业务层处理
 *
 * @author admin
 * @date 2021-09-09
 */
@Service
public class ExamPostInfoServiceImpl implements IExamPostInfoService {
    private static final Logger log = LoggerFactory.getLogger(ExamPostInfoServiceImpl.class);

    @Autowired
    private ExamPostInfoMapper examPostInfoMapper;

    @Autowired
    private ExamInfoMapper examInfoMapper;

    @Autowired
    private SysDictDataMapper sysDictDataMapper;

    @Autowired
    private SysDistrictMapper sysDistrictMapper;

    @Autowired
    private ServantExamineeInfoMapper servantExamineeInfoMapper;

    @Autowired
    private ServantExamineeSubjectGradeMapper servantExamineeSubjectGradeMapper;

    @Autowired
    private ExamPostScoreLineSettingSubMapper settingSubMapper;

    @Autowired
    private IChangedExamInfoService changedExamInfoService;
    /**
     * 批量插入的条数
     */
    public static final int BATCH_COUNT = 3000;

    //最大插入数
    public static final int MAX_IMPORT = 200;

    @Resource(name = "threadPoolTaskExecutor")
    protected ThreadPoolTaskExecutor threadPoolTaskExecutor;


    /**
     * 查询招考职位详细信息
     *
     * @param id 招考职位信息ID
     * @return 招考职位信息
     */
    @Override
    public ExamPostInfoVo selectExamPostInfoById(String id) {
        ExamPostInfoVo examPostInfoVo = new ExamPostInfoVo();
        ExamPostInfo examPostInfo = examPostInfoMapper.selectExamPostInfoById(id);
        BeanUtils.copyBeanProp(examPostInfoVo, examPostInfo);
        //考试类型
        ExamInfo examInfo = examInfoMapper.selectExamInfoById(examPostInfoVo.getExamId());
        examPostInfoVo.setExamType(sysDictDataMapper.selectDictLabel("exam_type", examInfo.getCivilServantType()));
        //字典翻译
        examPostInfoVo.setJgxzDictLabel(DictUtils.getDictLabel("exam_organ_nature", examPostInfoVo.getJgxz()));
        examPostInfoVo.setCjkscjDictLabel(DictUtils.getDictLabel("join_exam_tier", examPostInfo.getCjkscj()));
        examPostInfoVo.setLbDictLabel(DictUtils.getDictLabel("category", examPostInfoVo.getLb()));
        examPostInfoVo.setZwlbdictLabel(DictUtils.getDictLabel("position_category", examPostInfoVo.getZwlb()));
        examPostInfoVo.setZwcjDictLabel(DictUtils.getDictLabel("position_tier", examPostInfoVo.getZwcj()));
        examPostInfoVo.setSfzzzynlcsDictLabel(DictUtils.getDictLabel("sys_yes_no", examPostInfoVo.getSfzzzynlcs()));

        //地区名字转化
        examPostInfoVo.setGzddName(sysDistrictMapper.getAddress(examPostInfoVo.getGzdd()));
        examPostInfoVo.setLhddName(sysDistrictMapper.getAddress(examPostInfoVo.getLhdd()));

        //报名人数和实考人数，竞争比，最低录取分数线
        ServantExamineeInfo servantExamineeInfo = new ServantExamineeInfo();
        servantExamineeInfo.setExamId(examPostInfo.getExamId());
        servantExamineeInfo.setBkzwdm(examPostInfo.getZwdm());
        int registNum = servantExamineeInfoMapper.selectServantExamineeInfoCount(servantExamineeInfo); // 获取报名人数
        int realNum = servantExamineeSubjectGradeMapper.countRealNumByPost(examPostInfo.getExamId(), examPostInfo.getZwdm()) == null ? 0 : servantExamineeSubjectGradeMapper.countRealNumByPost(examPostInfo.getExamId(), examPostInfo.getZwdm());

        //如果没有考生，直接返回
        if (realNum ==0 || registNum ==0)
            return examPostInfoVo;

        examPostInfoVo.setRegisterNum(registNum);
        examPostInfoVo.setRealNum(realNum);

        double top =  new BigDecimal(registNum).divide(new BigDecimal(realNum)) .setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        String ratio = (Math.round(top) - top) == 0 ? String.valueOf((long) top) : String.valueOf(top);
        ratio = ratio + ":1";
        examPostInfoVo.setRatio(ratio);

        ExamScoreLineReq examScoreLineReq = new ExamScoreLineReq();
        examScoreLineReq.setExamId(examPostInfo.getExamId());
        examScoreLineReq.setZwdm(examPostInfo.getZwdm());
        examScoreLineReq.setDwdm(examPostInfo.getDwdm());
        String minSettingScore = settingSubMapper.selectMinSettingScore(examScoreLineReq);
        try {
            minSettingScore = new BigDecimal(minSettingScore).setScale(1, RoundingMode.HALF_UP).toString();
        } catch (NullPointerException e) {
            minSettingScore = null;
        }
        examPostInfoVo.setMinScore(minSettingScore);
        return examPostInfoVo;
    }

    /**
     * 查询招考职位信息列表
     *
     * @param examPostInfoReq 招考职位信息
     * @return 招考职位信息
     */
    @Override
    public List<ExamPostInfoRsp> selectExamPostInfoList(ExamPostInfoReq examPostInfoReq) {
        List<ExamPostInfoRsp> list = examPostInfoMapper.selectExamPostInfoList2(examPostInfoReq);
        for (ExamPostInfoRsp examPostInfoRsp : list) {
            examPostInfoRsp.setJgxzDictLabel(DictUtils.getDictLabel("exam_organ_nature", examPostInfoRsp.getJgxz()));
            examPostInfoRsp.setLbDictLabel(DictUtils.getDictLabel("category", examPostInfoRsp.getLb()));
            examPostInfoRsp.setZwlbdictLabel(DictUtils.getDictLabel("position_category", examPostInfoRsp.getZwlb()));
            examPostInfoRsp.setZwcjDictLabel(DictUtils.getDictLabel("position_tier", examPostInfoRsp.getZwcj()));

        }
        Comparator comparator = Collator.getInstance(Locale.CHINA);
        Collections.sort(list,((o1, o2) -> comparator.compare(o1.getZwmc(),o2.getZwmc())));
        return list;
    }

    /**
     * 新增招考职位信息
     *
     * @param examPostInfo 招考职位信息
     * @return 结果
     */
    @Override
    public int insertExamPostInfo(ExamPostInfo examPostInfo) {
        if (StringUtils.isBlank(examPostInfo.getId()))
            examPostInfo.setId(IdUtils.generateId());

        //判断新增的职位信息是否存在
        if (CollectionUtils.isNotEmpty(examPostInfoMapper.findExitExamPostInfo(examPostInfo))) {
            throw new CustomException(BizErrorCode.EXAM_E0009);
        }

        //转化成半角
        examPostInfo.setMsrybl(AsciiUtil.sbc2dbcCase(examPostInfo.getMsrybl()));

        //组装插入信息
        examPostInfo.setDeptId(SecurityUtils.getLoginUser().getUser().getDeptId());
        examPostInfo.setCreateBy(SecurityUtils.getUsername());
        examPostInfo.setCreateTime(DateUtils.getNowDate());
        examPostInfo.setUpdateTime(DateUtils.getNowDate());
        examPostInfo.setUpdateBy(SecurityUtils.getUsername());

        //拆分比例字符串，根据比例计算面试人数
        examPostInfo.setInterviewNum(this.getInterviewNum(examPostInfo.getZkrs(), examPostInfo.getMsrybl()));

        //插入考试变更记录
        changedExamInfoService.addChangedExamInfo(examPostInfo.getExamId());
        return examPostInfoMapper.insertExamPostInfo(examPostInfo);
    }

    /**
     * 修改招考职位信息
     *
     * @param examPostInfo 招考职位信息
     * @return 结果
     */
    @Override
    public int updateExamPostInfo(ExamPostInfo examPostInfo) {
        //判断职位是否存在
        if (examPostInfoMapper.selectExamPostInfoById(examPostInfo.getId()) == null)
            throw new CustomException(BizErrorCode.EXAM_E0010);

        examPostInfo.setUpdateTime(DateUtils.getNowDate());
        examPostInfo.setUpdateBy(SecurityUtils.getUsername());

        //拆分比例字符串，根据比例计算面试人数
        examPostInfo.setInterviewNum(this.getInterviewNum(examPostInfo.getZkrs(), examPostInfo.getMsrybl()));

        //插入考试变更记录
        changedExamInfoService.addChangedExamInfo(examPostInfo.getExamId());
        return examPostInfoMapper.updateExamPostInfo(examPostInfo);
    }

    /**
     * 拆分比例字符串，根据比例计算面试人数
     * @param zkrs 招考人数
     * @param msrybl 面试人员比例（如：1:2）
     * @return 结果 面试人数
     */
    private Integer getInterviewNum(Integer zkrs, String msrybl) {
        Integer interviewNum = 0;
        if (StringUtils.isNotEmpty(msrybl)) {
            String[] temp = StringUtils.split(msrybl, ":");
            BigDecimal top = new BigDecimal(temp[0]); // 分子
            BigDecimal buttom = new BigDecimal(temp[1]); // 分母
            BigDecimal msbl = top.divide(buttom, 4, BigDecimal.ROUND_UP);
            interviewNum = new BigDecimal(zkrs).divide(msbl, BigDecimal.ROUND_UP).intValue();
        }
        return interviewNum;
    }

    /**
     * 批量删除招考职位信息
     *
     * @param ids 需要删除的招考职位信息ID
     * @return 结果
     */
    @Override
    public int deleteExamPostInfoByIds(String[] ids) {
        //todo 校验是否存在考生成绩
        int num = examPostInfoMapper.queryExitExaminee(ids);
        if (num != 0) {
            return 0;
        }
        return examPostInfoMapper.deleteExamPostInfoByIds(ids);
    }

    /**
     * 删除招考职位信息信息
     *
     * @param id 招考职位信息ID
     * @return 结果
     */
    @Override
    public int deleteExamPostInfoById(String id) {
        //todo 校验是否存在考生成绩
        String[] ids ={id};
        int num = examPostInfoMapper.queryExitExaminee(ids);
        if (num != 0) {
            return 0;
        }
        return examPostInfoMapper.deleteExamPostInfoById(id);
    }

    /**
     * 下载职位导入模板
     *
     * @return
     */
    @Override
    public AjaxResult downloadTemplate() {
        return ExportUtils.downladTemplate(ImportFieldConstants.getPostFieldMap());
    }

    /**
     * 导入Excel文件
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public List<ImportPostInfoVo>  impotExcelPostInfo(MultipartFile multipartFile, String examId) {
        log.info("导入信息开始...文件类型为Excel");
        long startTime = System.currentTimeMillis();
        FileInputStream fileInputStream = null;
        List<ImportPostInfoVo> list = new ArrayList();

        //上传文件转化成输入流
        String fileName = multipartFile.getOriginalFilename();
        if(StringUtils.isEmpty(fileName)){
            return list;
        }
        String[] fileNameSplit = fileName.split("\\.");
        Workbook wb = null;
        try {
            File file = File.createTempFile(fileNameSplit[0], fileNameSplit[1]);
            multipartFile.transferTo(file);
            file.deleteOnExit();
            fileInputStream = new FileInputStream(file);
            //判断文件类型（xls/xlsx）
            if ("xls".equals(fileNameSplit[1])) {
                wb = new HSSFWorkbook(fileInputStream);
            } else if ("xlsx".equals(fileNameSplit[1])) {
                wb = new XSSFWorkbook(fileInputStream);
            }else {
                return null;
            }
            log.info("开始解析文件...");
            //开始解析
            Sheet sheet = wb.getSheetAt(0);
            Row headRow = sheet.getRow(sheet.getFirstRowNum());
            String[] fieldName = null;
            if (null != headRow) {
                int firstCellIndex = headRow.getFirstCellNum();
                int lastCellIndex = headRow.getLastCellNum();
                //获取字段名
                fieldName = new String[lastCellIndex];
                for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) {
                    Cell cell = headRow.getCell(cIndex);
                    if (null != cell)
                        fieldName[cIndex] = cell.toString();
                }
            }
            list = readImportFile(sheet, fieldName, examId);
        } catch (Exception e) {
            log.info("导入职位信息出现异常", e);
            throw new CustomException("导入职位信息出现异常");
        } finally {
            try {
                if(null != fileInputStream){
                    fileInputStream.close();
                }
                if(null != wb){
                    wb.close();
                }
                log.info("文件流关闭成功");
            } catch (Exception e) {
                log.info("文件流关闭失败");
            }
        }

        long endTime = System.currentTimeMillis();
        log.info("导入职位结束，总共耗时{}秒", (endTime - startTime) / 1000);
        return list;
    }

    /**
     * 批量插入职业信息
     *
     * @param list
     */
    @Override
    public void batchInsertExamPostInfo(List<ImportPostInfoVo> list) {
        log.info("插入职业信息begin...总共插入{}条数据，每次插入200条", list.size());
        //当前写入次数
        int insertNum = 1;
        //插入批次
        int curInsertTime = 1;
        //总共插入的次数
        int totalInsetNum = list.size() / MAX_IMPORT + 1;
        log.info("总共需要插入{}次", totalInsetNum);
        //需要插入的职位信息
        List<ExamPostInfo> insertPostInfoList = new ArrayList<>();

        for (ImportPostInfoVo importPostInfoVo : list) {
            insertPostInfoList.add(importPostInfoVo.getExamPostInfo());
            if (insertNum == MAX_IMPORT) {
                examPostInfoMapper.batchInsertPostInfo(insertPostInfoList);
                curInsertTime++;
                insertNum = 0;
                insertPostInfoList.clear();
            } else if ((curInsertTime - 1) * MAX_IMPORT + insertNum == list.size()) {
                examPostInfoMapper.batchInsertPostInfo(insertPostInfoList);
            }
            insertNum++;
        }
    }

    //读取excel信息
    private List<ImportPostInfoVo> readImportFile(Sheet sheet, String[] fieldName, String ExamId) throws Exception {
        //存放获取的字段信息
        Object[] rowValues = new Object[fieldName.length];
        //返回集合
        List<ImportPostInfoVo> list = new ArrayList<>();
        //错误信息
        List<ImportPostInfoVo> errorList = new ArrayList<>();
        //是否返回错误信息标记
        boolean flag = false;

        //读取Excel数据
        int firstRowIndex = sheet.getFirstRowNum() + 1;
        int lastRowIndex = sheet.getLastRowNum();

        // 获取已有职位信息
        Map<String, String> postCodeMap = new HashMap<>();
        ExamPostInfo examPostInfo1 = new ExamPostInfo();
        examPostInfo1.setExamId(ExamId);
        List<ExamPostInfo> postList = examPostInfoMapper.findExitExamPostInfo(examPostInfo1);
        if (!org.springframework.util.CollectionUtils.isEmpty(postList)) {
            postCodeMap = postList.stream().collect(Collectors.toMap(ExamPostInfo::getZwdm, ExamPostInfo::getZwdm));
        }

        log.info("开始写入实体类...");
        for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) { //遍历行
            Row row = sheet.getRow(rIndex);
            if (null != row) {
                for (int cIndex = 0; cIndex < fieldName.length; cIndex++)//遍历列
                {
                    Cell cell = row.getCell(cIndex);
                    rowValues[cIndex] = cell;
                    try{
                        if (cell.getCellType()==CellType.NUMERIC){
                            HSSFDataFormatter dateFormatter = new HSSFDataFormatter();
                            rowValues[cIndex] = dateFormatter.formatCellValue(cell);
                        }
                    } catch (NullPointerException e) {
                        rowValues[cIndex] = null;
                    }
                }

                //插入实体类
                ImportPostInfoVo importPostInfoVo = new ImportPostInfoVo();
                setPostInfo(importPostInfoVo, rowValues, ExamId, fieldName, postCodeMap, rIndex);

                if (StringUtils.isNotEmpty(importPostInfoVo.getErrorMsg())) {
                    errorList.add(importPostInfoVo);
                    flag = true;
                }
                list.add(importPostInfoVo);
            }
        }
        //如果有错误信息则返回
        if (flag) {
            return errorList;
        }
        //执行插入
        if (CollectionUtils.isNotEmpty(list)) {
            batchInsertPost(list);
        }
        return null;
    }

    /**
     * 设置职位信息
     */
    private void setPostInfo(ImportPostInfoVo importPostInfoVo, Object[] rowValues, String examId, String[] fieldName, Map<String, String> postCodeMap, int rowIndex) throws Exception {
        ExamPostInfo examPostInfo = importPostInfoVo.getExamPostInfo();
        //组装基本信息
        examPostInfo.setId(IdUtils.generateId());
        examPostInfo.setExamId(examId);
        examPostInfo.setCreateTime(DateUtils.getNowDate());
        examPostInfo.setCreateBy(SecurityUtils.getUsername());
        examPostInfo.setUpdateTime(DateUtils.getNowDate());
        examPostInfo.setUpdateBy(SecurityUtils.getUsername());
        examPostInfo.setDeptId(SecurityUtils.getLoginUser().getUser().getDeptId());

        for (int i = 0; i < fieldName.length; i++) {
            //数据校验
            if (ImportFieldConstants.getPostNotNullField().contains(fieldName[i])) {
                if (null == rowValues[i] || StringUtils.isEmpty(rowValues[i].toString())) {
                    importPostInfoVo.setErrorMsg("第" + (rowIndex + 1) + "行字段【" + fieldName[i] + "】对应的值为空,请检查！");
                    return;
                }
            }
            if ("职位代码".equals(fieldName[i])) {
                if (StringUtils.isNotEmpty(postCodeMap.get(rowValues[i].toString()))) {
                    log.info("职位代码已存在");
                    importPostInfoVo.setErrorMsg("职位代码为【" + rowValues[i] + "】的职位已存在，请检查！");
                }
            }
            //字段 序号 数据库没有相应字段，先忽略
            if ("序号".equals(fieldName[i])) {
                continue;
            }
            String ImportPostInfoField = ImportFieldConstants.getPostFieldMap().get(fieldName[i]);

            //半角转化
            if ("面试人员比例".equals(fieldName[i])) {
                rowValues[i] = AsciiUtil.sbc2dbcCase(rowValues[i].toString());
                //拆分比例字符串，根据比例计算面试人数
                examPostInfo.setInterviewNum(this.getInterviewNum(examPostInfo.getZkrs(),rowValues[i].toString()));
            }

            //组装对象
            if ("招考男女人数".equals(fieldName[i])) { //拆分招考男女人数
                String[] zkrs = null;
                Field zkrs_man = ExamPostInfo.class.getDeclaredField("zkrsMan");
                Field zkrs_woman = ExamPostInfo.class.getDeclaredField("zkrsWoman");
                zkrs_man.setAccessible(true);
                zkrs_woman.setAccessible(true);
                try {
                    rowValues[i] = AsciiUtil.sbc2dbcCase(rowValues[i].toString());
                    if (rowValues[i].toString().contains(":")) {
                        zkrs = rowValues[i].toString().split(":");
                    } else if (rowValues[i].toString().equals("")){
                        throw new NullPointerException();
                    } else {
                        System.out.println("第"+rowIndex);
                        throw new CustomException(BizErrorCode.EXAM_POST_E0002);
                    }

                    zkrs[1] = zkrs[1].replace(":", "");
                } catch (NullPointerException e) {
                    zkrs_man.set(examPostInfo, null);
                    zkrs_woman.set(examPostInfo, null);
                    continue;
                }
                zkrs_man.set(examPostInfo, Integer.parseInt(zkrs[0]));
                zkrs_woman.set(examPostInfo, Integer.parseInt(zkrs[1]));
                if (examPostInfo.getZkrs() != examPostInfo.getZkrsMan() + examPostInfo.getZkrsWoman())
                    importPostInfoVo.setErrorMsg("第" + (rowIndex + 1) + "行实招人数与男女招考人数之和不相等");

                continue;
            }

            //翻译字典
            if (ImportFieldConstants.getPostDirctField().contains(fieldName[i])){
                if (fieldName[i].equals("是否组织专业能力测试")) {
                    rowValues[i] = DictUtils.getDictValue("sys_yes_no",rowValues[i].toString());
                } else {
                    rowValues[i] = DictUtils.getDictValue(DictType.getPostDicrVaul().get(fieldName[i]), rowValues[i].toString());
                    if (null == rowValues[i] || StringUtils.isEmpty(rowValues[i].toString())) {
                        importPostInfoVo.setErrorMsg("第"+(rowIndex+1)+"行"+fieldName[i]+"填写错误");
                    }
                }
            }
            Field classField = ExamPostInfo.class.getDeclaredField(ImportPostInfoField);
            classField.setAccessible(true);
            ImportAbstractService.setFieldValue(examPostInfo, rowValues[i], classField);
        }

    }

    /**
     * 异步批量插入数据
     *
     * @param list
     */
    private void batchInsertPost(List<ImportPostInfoVo> list) {
        int count = list.size() % BATCH_COUNT == 0 ? list.size() / BATCH_COUNT : list.size() / BATCH_COUNT + 1;
        //线程倒数计算器
        CountDownLatch countDownLatch = new CountDownLatch(count);
        //存放线程结果
        List<FutureTask<Boolean>> resultList = Lists.newArrayList();

        //循环创建线程
        for (int i = 0; i < count; i++) {
            List<ImportPostInfoVo> importPostInfoVos = new ArrayList<>(BATCH_COUNT);
            if (i + 1 == count)
                importPostInfoVos.addAll(list.subList(i * BATCH_COUNT, list.size()));
            else
                importPostInfoVos.addAll(list.subList(i * BATCH_COUNT, (i + 1) * BATCH_COUNT));

            FutureTask<Boolean> futureTask = new FutureTask<>(new ImportPostTask(importPostInfoVos, countDownLatch));
            threadPoolTaskExecutor.submit(futureTask);
            resultList.add(futureTask);
        }

        try {
            countDownLatch.await();
            for (FutureTask<Boolean> futureTask : resultList) {
                if (!futureTask.get())
                    throw new CustomException(BizErrorCode.EXAM_POST_E0001);
            }
            log.info("异步批量插入职位任务完成" + DateUtils.localDateMillisToString(LocalDateTime.now()));
        } catch (InterruptedException e) {
            log.error(e.getCause().getMessage());
            Thread.currentThread().interrupt();
            throw new CustomException(BizErrorCode.EXAM_POST_E0001);
        } catch (ExecutionException e) {
            log.error(e.getCause().getMessage());
            throw new CustomException(BizErrorCode.EXAM_POST_E0001);
        }
    }

    /**
     * 异步插入职位处理
     */
    public class ImportPostTask implements Callable<Boolean> {

        private List<ImportPostInfoVo> postInfoVos;
        private CountDownLatch countDownLatch;

        public ImportPostTask(List<ImportPostInfoVo> postInfoVos, CountDownLatch countDownLatch) {
            this.postInfoVos = postInfoVos;
            this.countDownLatch = countDownLatch;
        }

        @Override
        public Boolean call() throws Exception {

            try {
                log.info("Savedate Size:{}", postInfoVos.size());
                batchInsertExamPostInfo(postInfoVos);
                return true;
            } finally {
                countDownLatch.countDown();
            }
        }
    }
}
